<?php
// +----------------------------------------------------------------------
// | Swoole服务端
// | TCP 服务器
// +----------------------------------------------------------------------

namespace helper;

use \Swoole\Server;

class SwooleServer
{
    private Server $server;

    public function __construct()
    {
        //创建Server对象，监听 127.0.0.1:9501 端口
        $server = new Server('127.0.0.1', 9501);
        $this->server = $server;
    }

    /**
     * 设置异步任务的工作进程数量
     * @return void
     */
    public function set()
    {
        $this->server->set([
            'task_worker_num' => 4, //进程的数量
            //'reactor_num' => 1,//默认值：CPU 核数 建议设置为 CPU 核数的 1-4 倍
            //'worker_num' => 4, //默认值：CPU 核数 建议设置为 CPU 核数的 1-4 倍
            //'max_request' => 100000,//设置 worker 进程的最大任务数
            //'daemonize' => 1, //以守护进程执行
            //'dispatch_mode' => 2,
            //"task_ipc_mode " => 3, //使用消息队列通信，并设置为争抢模式
        ]);
    }

    /**
     * 监听连接进入事件
     * @return void
     */
    public function connect()
    {
        $server = $this->server;
        $server->on('Connect', function ($server, $fd) {
            echo "Client: Connect." . PHP_EOL;
        });
    }

    /**
     * 监听数据接收事件
     * @return void
     */
    public function receive()
    {
        $server = $this->server;
        //此回调函数在worker进程中执行
        $server->on('Receive', function ($server, $fd, $reactor_id, $data) {
            //$server->send($fd, "Server: {$data}");
            //投递异步任务
            $task_id = $server->task($data);
            echo "Dispatch AsyncTask: id={$task_id}" . PHP_EOL;
        });
    }

    /**
     * 异步任务
     * 基于TCP实现
     * @param callable $callback
     * @return void
     */
    public function task(callable $callback)
    {
        $server = $this->server;
        //处理异步任务(此回调函数在task进程中执行)
        $server->on('Task', function ($server, $task_id, $reactor_id, $data) use ($callback) {
            echo "New AsyncTask[id={$task_id}]" . PHP_EOL;
            call_user_func($callback, $data);

            //返回任务执行的结果
            $server->finish("{$data} -> OK");
        });
    }

    /**
     * 处理异步任务的结果
     * @return void
     */
    public function finish()
    {
        $server = $this->server;
        //处理异步任务的结果(此回调函数在worker进程中执行)
        $server->on('Finish', function ($server, $task_id, $data) {
            echo "AsyncTask[{$task_id}] Finish: {$data}" . PHP_EOL;
        });
    }

    /**
     * 监听连接关闭事件
     * @return void
     */
    public function close()
    {
        $server = $this->server;
        $server->on('Close', function ($server, $fd) {
            echo "Client: Close.\n";
        });
    }

    /**
     * 启动服务器
     * @return void
     */
    public function start()
    {
       $this->server->start();
    }

    /**
     * WebSocket 服务器
     * @return void
     */
    public function ws_server()
    {
        //创建WebSocket Server对象，监听0.0.0.0:9502端口
        $ws = new \Swoole\WebSocket\Server('0.0.0.0', 9502);

        //监听WebSocket连接打开事件
        $ws->on('Open', function ($ws, $request) {
            $ws->push($request->fd, "hello, welcome\n");
        });

        //监听WebSocket消息事件
        $ws->on('Message', function ($ws, $frame) {
            echo "Message: {$frame->data}\n";
            $ws->push($frame->fd, "server: {$frame->data}");
        });

        //监听WebSocket连接关闭事件
        $ws->on('Close', function ($ws, $fd) {
            echo "client-{$fd} is closed\n";
        });

        $ws->start();
    }
}